package view.inventory;

import com.toedter.calendar.JDateChooser;
import java.awt.Color;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import main.ServicesList;
import model.inventory.Item;
import model.inventory.ItemHpp;
import model.inventory.ItemPrice;
import model.inventory.ItemPriceId;
import model.purchasing.OrderDetail;
import org.apache.log4j.Logger;
import utility.Constants;
import utility.NameValueList;
import utility.StringUtils;
import utility.com.TableCellListener;
import utility.com.TableUtil;
import utility.com.TextComponentUtils;
import utility.typeSafe.SalesPriceType;
import view.TransaksiTemplate;
import view.lookup.LookupSimpleFrm;

public final class ItemPriceFrm extends TransaksiTemplate {

    private static final int COL_LEVEL  = 0;
    private static final int COL_MARGIN = 1;
    private static final int COL_MARKUP = 2;
    private static final int COL_PRICE  = 3;
    
    final JTextField levelCE = new JTextField();
    final JTextField marginCE = new JTextField();
    final JTextField markupCE = new JTextField();
    final JTextField priceCE = new JTextField();
    
    private DefaultTableCellRenderer rightCellRender = new DefaultTableCellRenderer();
    private TableCellListener tableCellListener;
    private ItemListener itemListener = new StartDatesListener();
    private ItemHpp hpp;
    private ItemPrice itemPrice;
    private ItemPriceTM priceTM;
    private List<ItemPrice> itemPrices;

    private static Logger log = Logger.getLogger(ItemHppFrm.class);
    private Object oldValue, newValue;
    
    public ItemPriceFrm() {
        initComponents();
        initComponentsRules();
    }

    private void lookupMaster(String param) {
        Object object = new LookupSimpleFrm().execute(Constants.LOOKUP_ITEM, param); 
        if (object != null) { setMaster(object); }
    }
    
    private void setMaster(Object object) {
         if (object != null) {
            itemPrice.getId().setItemId(((Item) object).getId());
            itemPrice.setItem((Item) object);
            itemPrice.setUnit(((Item) object).getUnit());
            txtPLU.setText(((Item) object).getPlu());
            txtNama.setText(((Item) object).getNama());
            
            hpp = ServicesList.getItemHppService().get(itemPrice.getId().getItemId(), dtpStartDate.getDate());
            if(hpp!=null) { 
                itemPrice.setPkp(hpp.getPkp()); 
                showStartDates();
            }
            dtpStartDate.requestFocus();
        }
    }
    
    private void getMaster(String kode) {
        Item item = ServicesList.getItemService().getItem(kode);
        if (item != null) {setMaster(item); }
        else { lookupMaster(txtPLU.getText()); }
    }
    
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jToolBar1 = new javax.swing.JToolBar();
        btnNew = new javax.swing.JButton();
        btnSave = new javax.swing.JButton();
        btnDelete = new javax.swing.JButton();
        txtPLU = new javax.swing.JTextField();
        txtNama = new javax.swing.JTextField();
        dtpStartDate = new com.toedter.calendar.JDateChooser();
        rdHpp = new javax.swing.JRadioButton();
        rdAvg = new javax.swing.JRadioButton();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        txtHppBeforeTax = new javax.swing.JTextField();
        txtHppAfterTax = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        txtAvg = new javax.swing.JTextField();
        scrollPane = new javax.swing.JScrollPane();
        grid = new javax.swing.JTable();
        cmbDateHist = new javax.swing.JComboBox();
        jLabel6 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);
        jToolBar1.setMaximumSize(new java.awt.Dimension(32767, 20));
        jToolBar1.setSize(this.getWidth(), 50);

        btnNew.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit_add.png"))); // NOI18N
        btnNew.setText("Tambah");
        btnNew.setFocusable(false);
        btnNew.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnNew.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNewActionPerformed(evt);
            }
        });
        jToolBar1.add(btnNew);

        btnSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit.png"))); // NOI18N
        btnSave.setText("Save");
        btnSave.setFocusable(false);
        btnSave.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnSave.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSaveActionPerformed(evt);
            }
        });
        jToolBar1.add(btnSave);

        btnDelete.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit_remove.png"))); // NOI18N
        btnDelete.setText("Delete");
        btnDelete.setFocusable(false);
        btnDelete.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnDelete.setName("btnDelete"); // NOI18N
        btnDelete.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnDelete.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDeleteActionPerformed(evt);
            }
        });
        jToolBar1.add(btnDelete);

        txtPLU.setName("txtPLU"); // NOI18N

        txtNama.setEditable(false);
        txtNama.setFocusable(false);
        txtNama.setName("txtNama"); // NOI18N

        dtpStartDate.setDateFormatString("dd/MM/yyyy");
        dtpStartDate.setDoubleBuffered(false);
        dtpStartDate.setName("dtpStartDate"); // NOI18N

        buttonGroup1.add(rdHpp);
        rdHpp.setText("Harga Beli ");
        rdHpp.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        rdHpp.setName("rdHpp"); // NOI18N

        buttonGroup1.add(rdAvg);
        rdAvg.setText("Harga Rata-rata ");
        rdAvg.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        rdAvg.setName("rdAvg"); // NOI18N

        jLabel1.setText("PLU :");

        jLabel2.setText("Nama Barang :");

        jLabel3.setText("Start Date :");

        txtHppBeforeTax.setEditable(false);
        txtHppBeforeTax.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtHppBeforeTax.setFocusable(false);

        txtHppAfterTax.setEditable(false);
        txtHppAfterTax.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtHppAfterTax.setFocusable(false);

        jLabel4.setText("Sebelum PPN");

        jLabel5.setText("Sesudah PPN");

        txtAvg.setEditable(false);
        txtAvg.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtAvg.setFocusable(false);

        scrollPane.setName("scrollPane"); // NOI18N

        grid.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        grid.setName("grid"); // NOI18N
        scrollPane.setViewportView(grid);

        cmbDateHist.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        cmbDateHist.setName("cmbDateHist"); // NOI18N

        jLabel6.setText("Date Hist :");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(rdAvg, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(rdHpp, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(txtNama)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(txtPLU, javax.swing.GroupLayout.PREFERRED_SIZE, 129, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(txtHppBeforeTax, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(jLabel4))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel5)
                                    .addComponent(txtHppAfterTax, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addComponent(txtAvg, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(dtpStartDate, javax.swing.GroupLayout.PREFERRED_SIZE, 129, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jLabel6)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(cmbDateHist, javax.swing.GroupLayout.PREFERRED_SIZE, 111, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addComponent(scrollPane))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addGap(10, 10, 10))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtPLU, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtNama, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel2))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(dtpStartDate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel3)))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(cmbDateHist, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(jLabel6)))
                .addGap(14, 14, 14)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(jLabel5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(rdHpp)
                    .addComponent(txtHppBeforeTax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(txtHppAfterTax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(rdAvg)
                    .addComponent(txtAvg, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewActionPerformed
        initForm();
        txtPLU.requestFocus();
    }//GEN-LAST:event_btnNewActionPerformed

    private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveActionPerformed
        validasi();
    }//GEN-LAST:event_btnSaveActionPerformed

    private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteActionPerformed
        deleteRow();
    }//GEN-LAST:event_btnDeleteActionPerformed

    class ActionKeyListener implements KeyListener {
        @Override public void keyTyped(KeyEvent e) {} 
        @Override public void keyReleased(KeyEvent e) {}
        @Override public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) { 
                case KeyEvent.VK_F2: 
                    switch(e.getComponent().getName()) {
                        case "txtPLU": 
                            lookupMaster(txtPLU.getText()); 
                            break;
                    }; break;  
                
                case KeyEvent.VK_ENTER: 
                    switch(e.getComponent().getName()) {
                        case "txtPLU": 
                            newValue = txtPLU.getText();
                            if (!newValue.equals(oldValue)) { getMaster(txtPLU.getText()); }
                            else {moveNext();}
                            break;
                       default: moveNext(); break;
                    }; break;      
            }
        }
    }
    
    class ActionFocusGained implements FocusListener {
        @Override public void focusGained(FocusEvent e) { 
            Component componen = (Component) e.getSource(); 
            if (componen instanceof JTextField) { oldValue = ((JTextField) componen).getText();
            }else if (componen instanceof JComboBox) { oldValue = ((JComboBox) componen).getSelectedIndex();
            }else if (componen instanceof JCheckBox) { oldValue = ((JCheckBox) componen).isSelected();
            }else if (componen instanceof JTextArea) { oldValue = ((JTextArea) componen).getText(); 
            }else if (componen instanceof JDateChooser) { oldValue = ((JDateChooser) componen).getDate(); 
            }else if (componen instanceof JRadioButton) { oldValue = ((JRadioButton) componen).isSelected(); }
        }
        
        @Override public void focusLost(FocusEvent e) {
            Component componen = (Component) e.getSource(); 
            if (componen instanceof JTextField) { newValue = ((JTextField) componen).getText();
            }else if (componen instanceof JComboBox) { newValue = ((JComboBox) componen).getSelectedIndex();
            }else if (componen instanceof JCheckBox) { newValue = ((JCheckBox) componen).isSelected();
            }else if (componen instanceof JTextArea) { newValue = ((JTextArea) componen).getText(); 
            }else if (componen instanceof JDateChooser) { newValue = ((JDateChooser) componen).getDate(); 
            }else if (componen instanceof JRadioButton) { newValue = ((JRadioButton) componen).isSelected(); }
            if (!newValue.equals(oldValue)) { initButtonState(true); }
        }
    }

    class GridKeyListener implements KeyListener {
        @Override public void keyTyped(KeyEvent e) {};
        @Override public void keyReleased(KeyEvent e) {};
        
        @Override public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) { 
                case KeyEvent.VK_ENTER:
                    if ((grid.getSelectedRow() == grid.getRowCount()-1) 
                            && grid.getSelectedColumn() == COL_PRICE) {
                        itemPrices.add(new ItemPrice(new ItemPriceId(itemPrice.getId().getItemId(), dtpStartDate.getDate(), grid.getRowCount()+1)));
                        priceTM.fireTableDataChanged(); 
                    }
                    break;
            }        
        };
    }
    
    Action DetailAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            TableCellListener tblCellListener = (TableCellListener)e.getSource();
            int row = tblCellListener.getRow();
            int col = tblCellListener.getColumn();
                
            Object oldVal = tblCellListener.getOldValue();
            Object newVal = tblCellListener.getNewValue();
            
            if(oldVal==null) {oldVal="";}
            if(newVal==null) {newVal="";}
                
            if (!oldVal.equals(newValue)) {
                switch (col) {
                    case COL_LEVEL: 
                        itemPrices.get(row).getId().setPriceLevel((Integer)newVal);
                        priceTM.fireTableCellUpdated(row, col);
                        initButtonState(true);
                        break;
                    case COL_MARGIN: 
                        BigDecimal margin = TextComponentUtils.parseNumberToBigDecimal((String)newVal);
                        itemPrices.get(row).setMargin(margin);
                        priceTM.fireTableCellUpdated(row, col);
                        calculate(row, col);
                        initButtonState(true);
                        break;
                    case COL_MARKUP: 
                        BigDecimal markup = TextComponentUtils.parseNumberToBigDecimal((String)newVal);
                        itemPrices.get(row).setMargin(markup);
                        priceTM.fireTableCellUpdated(row, col);
                        calculate(row, col);
                        initButtonState(true);
                        break;
                    case COL_PRICE: 
                        BigDecimal price = TextComponentUtils.parseNumberToBigDecimal((String)newVal);
                        itemPrices.get(row).setMargin(price);
                        priceTM.fireTableRowsUpdated(row, row);
                        calculate(row, col);
                        initButtonState(true);
                        break;    
                }
            }
        }
    };    
    
    class StartDatesListener implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent e) {
            if(e.getStateChange()==ItemEvent.SELECTED) {
                loadData();
            }
        }
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnDelete;
    private javax.swing.JButton btnNew;
    private javax.swing.JButton btnSave;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JComboBox cmbDateHist;
    private com.toedter.calendar.JDateChooser dtpStartDate;
    private javax.swing.JTable grid;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JRadioButton rdAvg;
    private javax.swing.JRadioButton rdHpp;
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JTextField txtAvg;
    private javax.swing.JTextField txtHppAfterTax;
    private javax.swing.JTextField txtHppBeforeTax;
    private javax.swing.JTextField txtNama;
    private javax.swing.JTextField txtPLU;
    // End of variables declaration//GEN-END:variables

    @Override
    public void setVisible(boolean value) {
        super.setVisible(value);
        txtPLU.requestFocusInWindow();
    }
    
    private int getActivePriceIdx() {
        Date curdate = StringUtils.truncDate(new Date());
        for (int i=0; i<cmbDateHist.getItemCount(); i++) {
            Date startDate = StringUtils.stringToDate((String) cmbDateHist.getItemAt(i));
            if (startDate.compareTo(curdate) <= 0) {
                return i;
            }
        }
        return -1;
    }
    
    private void showStartDates() {
        cmbDateHist.removeItemListener(itemListener);
        cmbDateHist.setModel(new DefaultComboBoxModel());
        List<Date> dates = ServicesList.getItemPriceService().getDates(itemPrice.getId().getItemId());
        DefaultComboBoxModel cbModel = new DefaultComboBoxModel();
        for (Date date : dates) {
            cbModel.addElement(StringUtils.formatDate(date));
        }
        cmbDateHist.setModel(cbModel);
        if(cbModel.getSize()==1) {loadData();}
        else if(cbModel.getSize()>1) {
            int priceActive = getActivePriceIdx();
            
            if (priceActive > -1) {
                cmbDateHist.setSelectedIndex(priceActive);
                loadData();
            }
        }
        
        cmbDateHist.addItemListener(itemListener);
    }
    
    private void moveNext() {
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.focusNextComponent();
    }
    
    @Override
    public void execute(boolean withVisible, int id) {
        setLocationRelativeTo(null);
        initForm();
        if (withVisible) { setVisible(true); }
    }

    @Override
    protected void initForm() {
        txtAvg.setText("0");
        txtHppAfterTax.setText("0");
        txtHppBeforeTax.setText("0");
        txtNama.setText("");
        txtPLU.setText("");
        dtpStartDate.setDate(StringUtils.truncDate(new Date()));
        rdHpp.setSelected(true);
        itemPrice = new ItemPrice();
        itemPrices = new ArrayList<>();
        itemPrices.add(new ItemPrice());
        priceTM = new ItemPriceTM(itemPrices);
        initGrid();
    }

    @Override
    protected void initGrid() {
        grid.removePropertyChangeListener(tableCellListener);
        grid.setModel(priceTM);
        
        grid.getColumnModel().getColumn(COL_LEVEL).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_MARGIN).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_MARKUP).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_PRICE).setCellRenderer(rightCellRender);
        
        grid.getColumnModel().getColumn(COL_LEVEL).setCellEditor(new DefaultCellEditor (levelCE));
        grid.getColumnModel().getColumn(COL_MARGIN).setCellEditor(new DefaultCellEditor (marginCE));
        grid.getColumnModel().getColumn(COL_MARKUP).setCellEditor(new DefaultCellEditor (markupCE));
        grid.getColumnModel().getColumn(COL_PRICE).setCellEditor(new DefaultCellEditor (priceCE));
        
        grid.getColumnModel().getColumn(COL_LEVEL).setPreferredWidth(60);
        grid.getColumnModel().getColumn(COL_MARGIN).setPreferredWidth(90);
        grid.getColumnModel().getColumn(COL_MARKUP).setPreferredWidth(100);
        grid.getColumnModel().getColumn(COL_PRICE).setPreferredWidth(100);
        
        grid.getColumnModel().getColumn(COL_LEVEL).setMaxWidth(60);
        grid.getColumnModel().getColumn(COL_MARGIN).setMaxWidth(90);
        grid.getColumnModel().getColumn(COL_MARKUP).setMaxWidth(100);
        grid.getColumnModel().getColumn(COL_PRICE).setMaxWidth(100);
        
        //look style
        final TableCellRenderer header = grid.getTableHeader().getDefaultRenderer();
        grid.getTableHeader().setDefaultRenderer(new TableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                JLabel lbl = (JLabel) header.getTableCellRendererComponent(table, 
                      value, isSelected, hasFocus, row, column);
                lbl.setBorder(BorderFactory.createEmptyBorder(5,1,5,1));   
                lbl.setHorizontalAlignment(SwingConstants.RIGHT);    
                lbl.setForeground(Color.WHITE);
                lbl.setBackground(Color.DARK_GRAY);
                return lbl;
            }
        });
        grid.setGridColor(Color.LIGHT_GRAY);
        tableCellListener = new TableCellListener(grid, DetailAction);
    }

    @Override
    protected void loadData() {
        itemPrice.getId().setStartDate(StringUtils.stringToDate((String)cmbDateHist.getSelectedItem()));
                
        Map<NameValueList, Object> params = new HashMap<>();
        params.put(new NameValueList("itemPrice.id.itemId", Constants.OPERATOR_EQUAL), itemPrice.getId().getItemId()); 
        params.put(new NameValueList("itemPrice.id.startDate", Constants.OPERATOR_EQUAL), itemPrice.getId().getStartDate()); 
        params.put(new NameValueList(null, Constants.OPERATOR_ORDERBY), "itemPrice.id.priceLevel"); 
        
        itemPrices = ServicesList.getItemPriceService().getAll(params);
        if (itemPrices==null || itemPrices.isEmpty()) {
            itemPrices = new ArrayList<>();
            itemPrices.add(itemPrice);
        }        
        
        priceTM = new ItemPriceTM(itemPrices);
        initGrid();
        
        dtpStartDate.setDate(itemPrice.getId().getStartDate());
        rdHpp.setSelected(itemPrices.get(0).getSumber().equals(SalesPriceType.HPP.toString()) ? true:false); 
        rdAvg.setSelected(itemPrices.get(0).getSumber().equals(SalesPriceType.AVG.toString()) ? true:false); 
            
        if(hpp!=null) {
            BigDecimal hppAfterPpn = hpp.getHppAfterPpn().divide(new BigDecimal(hpp.getFraksi()), 2, RoundingMode.HALF_EVEN);
            BigDecimal hppBeforePpn = hpp.getHpp().divide(new BigDecimal(hpp.getFraksi()), 2, RoundingMode.HALF_EVEN);
            txtHppBeforeTax.setText(TextComponentUtils.formatNumberShowDecimal(hppBeforePpn, 2));
            txtHppAfterTax.setText(TextComponentUtils.formatNumberShowDecimal(hppAfterPpn, 2));
        }
    }

    @Override
    protected void saveData() {
        for (int i=0; i<itemPrices.size(); i++) {
            itemPrices.get(i).setFraksi(1);
            itemPrices.get(i).getId().setItemId(itemPrice.getId().getItemId());
            itemPrices.get(i).getId().setStartDate(itemPrice.getId().getStartDate());
            itemPrices.get(i).setUnit(itemPrice.getUnit());
        }
        
        boolean saved = ServicesList.getItemPriceService().save(itemPrices);
        if (!saved) {
            JOptionPane.showMessageDialog(this, "Data gagal disimpan.", "Error",JOptionPane.ERROR_MESSAGE);
        }
        initButtonState(!saved);
    }

    @Override
    protected void validasi() {
        boolean valid = hpp != null && itemPrice.getId().getItemId() > 0 ? true:false;
        if (!valid) {
            JOptionPane.showMessageDialog(this, "Inputan blm lengkap.!", "Warning",JOptionPane.WARNING_MESSAGE);}
        if (valid) { saveData(); }
    }

    @Override
    protected void posting() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected void initButtonState(boolean state) {
        btnSave.setEnabled(state);
    }

    @Override
    protected void initComponentsRules() {
        rightCellRender.setHorizontalAlignment(SwingConstants.RIGHT);
        TextComponentUtils.setNumericTextOnly(levelCE);
        TextComponentUtils.setCurrency(marginCE);
        TextComponentUtils.setCurrency(markupCE);
        TextComponentUtils.setCurrency(priceCE);
        
        levelCE.setHorizontalAlignment(SwingConstants.RIGHT);
        marginCE.setHorizontalAlignment(SwingConstants.RIGHT);
        markupCE.setHorizontalAlignment(SwingConstants.RIGHT);
        priceCE.setHorizontalAlignment(SwingConstants.RIGHT);
        
        txtPLU.addKeyListener(new ActionKeyListener());
        txtPLU.addFocusListener(new ActionFocusGained());
        
        dtpStartDate.getDateEditor().addPropertyChangeListener(
            new PropertyChangeListener() {
            @Override public void propertyChange(PropertyChangeEvent evt) {
                if (itemPrices != null) {
                    if ("date".equals(evt.getPropertyName())) {
                        if(!evt.getNewValue().equals(evt.getOldValue())) {

                            hpp = ServicesList.getItemHppService().get(itemPrice.getId().getItemId(), dtpStartDate.getDate());
                            if(hpp!=null) { itemPrice.setPkp(hpp.getPkp()); }

                            itemPrice.getId().setStartDate(StringUtils.truncDate((Date) evt.getNewValue()));
                            for (ItemPrice price : itemPrices) {
                                price.getId().setStartDate(StringUtils.truncDate((Date) evt.getNewValue()));
                            }
                        }
                    }
                }
            }
        });
        
        TableUtil.setTableActionKeyMap(grid);
        grid.addKeyListener(new GridKeyListener());
        cmbDateHist.setModel(new DefaultComboBoxModel());
    }
    
    private void calculate(int row, int col) {
        if (hpp!=null) {
            BigDecimal margin = itemPrices.get(row).getMargin();
            BigDecimal markup = itemPrices.get(row).getMarkup();
            BigDecimal price = itemPrices.get(row).getPrice();
            BigDecimal net = TextComponentUtils.parseNumberToBigDecimal((String)txtHppAfterTax.getText());
            
            if (col==COL_MARGIN) {
                margin = margin.divide(Constants.PERSENT_DIVIDER, 2, RoundingMode.HALF_EVEN);
                price = margin.multiply(net).setScale(0, RoundingMode.HALF_EVEN).add(net);
                markup = price.subtract(net).setScale(2, RoundingMode.HALF_EVEN);
                
                itemPrices.get(row).setMarkup(markup);
                itemPrices.get(row).setPrice(price);

            } else if (col==COL_MARKUP) {
                price = net.add(markup);
                margin = price.subtract(net).divide(net).multiply(Constants.PERSENT_DIVIDER).setScale(2, RoundingMode.HALF_EVEN);
                itemPrices.get(row).setMargin(margin);
                itemPrices.get(row).setPrice(price);

            }else if (col==COL_PRICE) {
                markup = price.subtract(net).setScale(2, RoundingMode.HALF_EVEN);
                margin = price.subtract(net).divide(net).multiply(Constants.PERSENT_DIVIDER).setScale(2, RoundingMode.HALF_EVEN);
                itemPrices.get(row).setMargin(margin);
                itemPrices.get(row).setMarkup(markup);
            }
            
            priceTM.fireTableRowsUpdated(row, row);
        }
    }
    
    private void deleteRow () {
        int rowCount = grid.getRowCount();
        int row = grid.getSelectedRow();
        
        ItemPrice deletedData = itemPrices.get(row);
        boolean saved = ServicesList.getItemPriceService().delete(deletedData);
        if (!saved) {
            JOptionPane.showMessageDialog(this, "Data gagal dihapus.", "Error",JOptionPane.ERROR_MESSAGE);
        
        }else {
        
            if (rowCount==1) {
                itemPrices.set(row, itemPrice);
                priceTM.fireTableRowsUpdated(row, row);
            } else {
                itemPrices.remove(row);
                priceTM.fireTableRowsDeleted(row, row);
            }
        }
    }
    
    private void setTableLookStyle() {
        
    }
}
